﻿package 
{
	import bipede.animation.AnimationTimer;
	import bipede.animation.Marche;
	import bipede.animation.Pose;
	import bipede.animation.Posture;
	import bipede.animation.SceneManager;
	import bipede.animation.Sequenceur;
	import bipede.animation.Timeline;
	import bipede.controleurs.Animateur;
	import bipede.membres.Squelette;
	import bipede.user.Voiture;
	import bipede.membres.Person;
	import bipede.membres.PhysicJoint;
	import drawer.DrawManager;
	import drawer.events.DrawEvent;
	import events.MarcheEvent;
	import events.PersonEvent;
	import events.PlateformeEvent;
	import fab.geom.Circle;
	import flash.display.DisplayObject;
	import flash.display.StageDisplayState;
	import games.thewalker.Data;
	import physic.elements.Ascenceur;
	
	import bipede.data.Allures;
	import events.UserEvent;
	import fab.geom.Cone;
	import fab.geom.Drawer;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.*;
	import events.MoveEvent;
	import physic.*;
	import flash.display.Bitmap;
	import flash.display.BitmapData;	
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import clips.Draggable;
	import flash.display.StageScaleMode;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
	public class TheWalker extends MovieClip
	{
		static public var zone_utile : Rectangle;
		static public var Width : int = 900;
		static public var Height : int = 700;
		static public var instance:TheWalker;
		static public var drawings:Sprite;
		static public var current_perso:Person;
		private var _bloc:Obstacle;
		private var sequenceur:Sequenceur;
		private var data:Data;
		private var drawManager:DrawManager;
		private var persos:Array=new Array();
		private var compteur_perso:int=0;
		
		public function TheWalker()
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			instance = this;
			addEventListener(Event.ADDED_TO_STAGE, init );
		}
		public function init(pEvt=null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			stage.displayState = StageDisplayState.FULL_SCREEN;
			
			// Drawings
				
			drawings = new Sprite();
			addChild( drawings );
			drawManager = new DrawManager( drawings.graphics );
			
			// Data
			
			data = new Data();
			
            stage.addEventListener(Event.ACTIVATE, activateHandler );
            stage.addEventListener(Event.RESIZE, resizeHandler );
            stage.addEventListener( MouseEvent.CLICK, _clic );
			
			// Persos
			
			var alfred:Person = new IKPerson1();
			alfred.name = "alfred";
			alfred.x = 300;
			alfred.y = 0;
			addChild( alfred );
			alfred.data = data.alfred_data;
			alfred.addEventListener( PersonEvent.ARMATURE_READY, data.set_animations );
			alfred.addEventListener( PersonEvent.ANIMATIONS_READY, _animations_ready );

			var alphonse:Person = new IKPerson2();
			alphonse.name = "alphonse";
			alphonse.x = 600;
			alphonse.y = 0;
			addChild( alphonse );
			alphonse.data = data.alphonse_data;
			alphonse.addEventListener( PersonEvent.ARMATURE_READY, data.set_animations );
			alphonse.addEventListener( PersonEvent.ANIMATIONS_READY, _animations_ready );
			
			addEventListener( PersonEvent.ALL_PERSON_READY, _all_person_ready );
			
			//persos.push( alfred );
			persos.push( alphonse );
			current_perso = persos[ 0 ];
			
			// désativer le controle des pantins
			
			IKManager.trackAllArmatures(false);
			
			// Physics & physic.Elements
			
			Engine.espace = this;
			for each( var perso in persos )
			{
				//perso.physics = Engine.registerSoftBody( perso );
				//SceneManager.register( perso );
			}
			
			_bloc = Engine.registerObstacle( bloc1, new Point( bloc1.p1.x, bloc1.p1.y ), new Point( bloc1.p2.x, bloc1.p2.y ) );
			var _bloc2:Obstacle = Engine.registerObstacle( bloc2, new Point( bloc2.p1.x, bloc2.p1.y ), new Point( bloc2.p2.x, bloc2.p2.y ) );// new Point( 0, 0 ), new Point( 100, -20 ) );
			var _bloc3:Obstacle = Engine.registerObstacle( bloc3, new Point( bloc3.p1.x, bloc3.p1.y ), new Point( bloc3.p2.x, bloc3.p2.y ) );//, new Point( 0,0 ), new Point( 100,80 ) );
			var _bloc4:Obstacle = Engine.registerObstacle( bloc4, new Point( bloc4.p1.x, bloc4.p1.y ), new Point( bloc4.p2.x, bloc4.p2.y ) );//, new Point( 0, 0 ), new Point( 100, -60 ) );	
			
			Engine.registerHandle( handle1 );
			Engine.registerHandle( handle2 );
			
			//var _ascenceur1:Obstacle = Engine.registerObstacle( ascenceur1, new Point( ascenceur1.p1.x, ascenceur1.p1.y ), new Point( ascenceur1.p2.x, ascenceur1.p2.y ) );
			//(ascenceur1 as MovieClip).addEventListener( PlateformeEvent.UPDATE, _ascenceur1.updatePlateforme );
			//_ascenceur1.addEventListener( DrawEvent.DRAWSEGMENT, drawManager.drawSegment );

			// User events
			
			var key:Voiture = new Voiture();
			key.addEventListener( UserEvent.DOWN, press_key_down );
			key.addEventListener( UserEvent.UP, press_key_up );
			key.addEventListener( UserEvent.RIGHT, press_key_right );
			key.addEventListener( UserEvent.LEFT, press_key_left );
			key.addEventListener( UserEvent.RELEASE_SPACE, release_space );
			key.addEventListener( UserEvent.RELEASE_DOWN, release_key_down );
			key.addEventListener( UserEvent.RELEASE_LEFT, release_key_left );
			key.addEventListener( UserEvent.RELEASE_RIGHT, release_key_right );
			key.addEventListener( UserEvent.RELEASE_UP, release_key_up );	
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, key.keyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP, key.keyUpHandler);	
			
			//dragg_perso.lockCenter = true;
			//dragg_perso.addEventListener( MoveEvent.STARTMOVING, perso[ 0 ].startmoving );
			//dragg_perso.addEventListener( MoveEvent.ENDMOVING, perso[ 0 ].endmoving );
			//dragg_perso.addEventListener( MoveEvent.MOVING, perso[ 0 ].move );// moving );
		}
		private function _animations_ready( event:PersonEvent ):void
		{
			trace ( event.target.name + " Ready" );
			
			switch( event.target.name )
			{
				case "alfred" :
				case "alphonse" :

				var _perso:Person = event.target as Person;
				//_perso.addEventListener( DrawEvent.DRAWRECTANGLE, drawManager.drawRectangle );
				//_perso.yeux.addEventListener( DrawEvent.DRAWLINE, drawManager.drawLine );
				//_perso.yeux.addEventListener( DrawEvent.DRAWPOINT, drawManager.drawPoint );

				//_perso.orientation = false;
				//_perso.repose( new MoveEvent( MoveEvent.REPOSE, null, _bloc ) );
				//_perso.support = _bloc;// TODO faire atterrir le perso
				
				stage.addEventListener( MouseEvent.MOUSE_MOVE, _perso.yeux.mouse_move );

				_perso.animateurs.marche.anim.addEventListener( MarcheEvent.FIN_PAS, fin_pas );
				_perso.addEventListener( MarcheEvent.NO_SUPPORT, no_support );				
				//_perso.animateurs.marche.anim.addEventListener( DrawEvent.DRAWCURVE, drawManager.draw_curve );
				
				break;
			}
			
			compteur_perso++;
			if ( compteur_perso == persos.length ) dispatchEvent( new PersonEvent( PersonEvent.ALL_PERSON_READY ) );
		}
		private function _all_person_ready(e:PersonEvent):void 
		{
			for each( var perso in persos )
			{
				perso.physics = Engine.registerSoftBody( perso );
			}			
			Engine.getInstance().start();
			
			//stage.addEventListener( MouseEvent.MOUSE_MOVE, _mouse_move );
			
			// test "voir les obstacles"
			//var image:Bitmap = new Bitmap( Engine.zone_obstacles );
			//addChild(image);			
		}

		private function no_support(event:MarcheEvent):void 
		{
			trace("no_support");
			
			// redemarrage
			//current_perso.animateurs.marche.start();// provoque infinite loop
			
			balance_les_bras();
		}		
		private function balance_les_bras():void 
		{
			current_perso.animateurs.bras_ballants.configure( { support:current_perso.support } );	
			current_perso.animateurs.bras_ballants.start();
		}		
		private function fin_pas(event:MarcheEvent):void 
		{
			// retournement
			trace("fin_pas");
			if ( current_perso.orientation != ( stage.mouseX > current_perso.x ) && Math.abs( stage.mouseX - current_perso.x ) > 200 )
			{
				// attendre la fin du pas ?
				current_perso.orientation = ( stage.mouseX > current_perso.x );
				//current_perso.repose( new MoveEvent( MoveEvent.REPOSE, null, _bloc ) );
			}
		}
		
		// user commande
		
		private function _clic(e:MouseEvent):void 
		{
			balance_les_bras();
		}		
		private function _mouse_move(event:MouseEvent):void 
		{
			var current_support:Obstacle = current_perso.support;
			//trace( "current_support " , current_support);
			if ( current_support == null ) return;
			
			// redemarrage de la marche si blocage !??
			
			if ( current_perso.animateurs.marche != null && !current_perso.animateurs.marche.running && Math.abs( stage.mouseX - current_perso.x ) > 200 )
			{
				//current_perso.animateurs.leve_les_bras.start();
				//sequenceur.start();
				current_perso.orientation = ( stage.mouseX > current_perso.x );
				
				current_perso.animateurs.marche.start();
			}
		}
		
		private function configure_accroupissement():void 
		{
			var current_support:Obstacle = current_perso.support;
			if ( current_support == null ) return;
			
			// calcul du point bas du Person p/r au support _bloc
			var p:Point = current_support.plateforme.projection( current_perso.place );
			var cercle:Circle = new Circle( p, current_perso.data.distance_support_accroupi );
			var cible:Point = cercle.projection( current_perso.place, true, true );	
			
			// config de l'accroupissement
			current_perso.animateurs.accroupi.configure( { 
				support:current_support, 
				sujet:current_perso,
				place:current_perso.place,
				cible:cible
			} );
			//current_perso.animateurs.accroupi.start();
		}		
		private function press_key_down(e:UserEvent):void 
		{
			if ( current_perso.animateurs.marche != null && current_perso.animateurs.marche.running ) return;
			
			var current_support:Obstacle = current_perso.support;
			trace( "current_support " , current_support);
			if ( current_support == null ) return;
			trace( "current_");
			if ( current_perso.animateurs.accroupi.running )
			{trace( "currdddent_");
				if ( !current_perso.animateurs.accroupi.sens )
				{
					current_perso.animateurs.accroupi.reverse();
				}					
			}
			else {trace( "current_");
				var coeff_accroupissement:Number = ( current_perso.distance_au_support( current_support ) - current_perso.data.distance_support_accroupi) / ( current_perso.data.distance_support - current_perso.data.distance_support_accroupi);
				//if ( coeff_accroupissement >= 1 )
				if ( current_perso.distance_au_support( current_support ) > current_perso.data.distance_support_accroupi )
				{trace( "currssent_");
					configure_accroupissement();
					current_perso.animateurs.accroupi.start();
				}
			}
		}

		private function release_key_down(e:UserEvent):void 
		{
			var current_support:Obstacle = current_perso.support;
			if ( current_support == null ) return;

			trace(current_perso.distance_au_support( current_support ), current_perso.data.distance_support_accroupi, current_perso.data.distance_support );
			var coeff_accroupissement:Number = (current_perso.distance_au_support( current_support ) - current_perso.data.distance_support_accroupi) / ( current_perso.data.distance_support - current_perso.data.distance_support_accroupi);
			
			var direction:Point = current_perso.yeux.regard.directeur;
			trace(direction);
			
			if( coeff_accroupissement < 1 && direction.y < 0 )//stage.mouseY < current_perso.place.y )// SAUT
			{
				current_perso.animateurs.accroupi.stop();
				//current_perso.animateurs.accroupi = null;
				
				// mise à jour du regard
				
				//stage.removeEventListener( MouseEvent.MOUSE_MOVE, current_perso.yeux.mouse_move );
				stage.dispatchEvent( new MouseEvent( MouseEvent.MOUSE_MOVE, true, false, stage.mouseX, stage.mouseY ) );
				
				// calcul du point bas du Person p/r au support _bloc
				
				var p:Point = current_support.plateforme.projection( current_perso.place );
				var cercle:Circle = new Circle( p, current_perso.data.distance_support_max );
				
				var impulsion:int = Math.min( 50, 50 * (1 - coeff_accroupissement) );
				
				var vitesse_sujet:Point = new Point( direction.x * impulsion, direction.y * impulsion );
				var cible:Point = cercle.projection( current_perso.place.add( vitesse_sujet ), true, false );	
				
				//Drawer.drawCircle(drawings.graphics, cercle.centre, cercle.rayon );
				//Drawer.drawPoint(drawings.graphics, vitesse_sujet, 0xFF00FF);
				//Drawer.drawPoint(drawings.graphics, cible, 0xFF0000);
				//Drawer.drawPoint(drawings.graphics, direction, 0x000000);
				
				trace("SAUT : coeff " ,coeff_accroupissement,cible,"   ",direction,vitesse_sujet );
				
				current_perso.animateurs.saut.configure( { 
					support:current_support, 
					place:current_perso.place,
					cible:cible,
					vitesse_sujet:vitesse_sujet
					} );
				current_perso.animateurs.saut.start();	
				//(saut.anim as Saut).addEventListener( DrawEvent.DRAWCURVE, drawManager.draw_curve );
			}
			else {// on se releve
				current_perso.animateurs.accroupi.stop();
				current_perso.animateurs.accroupi.reset();
				current_perso.animateurs.accroupi.reverse();
			}
		}
		private function release_space(e:UserEvent):void 
		{
			current_perso.select(false);
			for ( var p:int = 0; p < persos.length; p++ ) if ( persos[ p ] == current_perso ) break;
			current_perso = ( p == persos.length - 1 )?persos[ 0 ]:persos[ p + 1 ];
			current_perso.select();
			trace( "current_perso ", current_perso.name);
		}
		private function release_key_up(e:UserEvent):void 
		{

		}
		
		private function release_key_right(e:UserEvent):void 
		{
			
		}
		
		private function release_key_left(e:UserEvent):void 
		{
			
		}
		private function press_key_up(e:UserEvent):void 
		{
			
		}
		private function press_key_left(e:UserEvent):void 
		{
			if ( !current_perso.orientation && current_perso.animateurs.marche.running ) return;
			current_perso.orientation = false;
			_start_marche();		
		}
		
		private function press_key_right(e:UserEvent):void 
		{
			if ( current_perso.orientation && current_perso.animateurs.marche.running ) return;
			current_perso.orientation = true;
			_start_marche();
		}
		private function _start_marche():void 
		{
			current_perso.animateurs.accroupi.stop();
			if ( current_perso.animateurs.marche != null )
			{
				//current_perso.repose( new MoveEvent( MoveEvent.REPOSE, current_perso.place, _bloc ) );
				current_perso.animateurs.marche.configure( { 
					orientation:current_perso.orientation
				} );
				//current_perso.animateurs.bras_ballants.stop();
				current_perso.animateurs.marche.start();
			}
		}
		
		// stage manip

        private function activateHandler(event:Event):void {
            trace("activateHandler: " + event);
			updateSize();
        }
        private function resizeHandler(event:Event):void {
            trace("resizeHandler: " + event);
            trace("stageWidth: " + stage.stageWidth + " stageHeight: " + stage.stageHeight);
			updateSize();			
        }
        private function updateSize():void
		{
			zone_utile = new Rectangle( int( Width - stage.stageWidth )/2, int( Height - stage.stageHeight )/2, int( stage.stageWidth ), int( stage.stageHeight ) );
			//zone_utile = zone_utile.intersection( MAX_ZONE ).union( MIN_ZONE );
			zone_utile.inflate( -1, -1 );
			//graphics.clear();
			//graphics.lineStyle( 0, 0x666666 );
			//graphics.drawRect( zone_utile.x, zone_utile.y, zone_utile.width, zone_utile.height );
        }			
	}
}